package com.chagee.channel.server.event.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.mts20140618.Client;
import com.aliyun.mts20140618.models.SubmitJobsRequest;
import com.aliyun.mts20140618.models.SubmitJobsResponse;
import com.aliyun.oss.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.chagee.channel.api.bo.oss.*;
import com.chagee.channel.api.enums.DocumentConversionSourceEnum;
import com.chagee.channel.api.enums.DocumentConversionTargetEnum;
import com.chagee.channel.common.exception.BizErrorCode;
import com.chagee.channel.common.exception.BizException;
import com.chagee.channel.server.config.OssConfig;
import com.chagee.channel.server.config.OssCustomConfig;
import com.chagee.channel.server.enums.BusinessEnum;
import com.chagee.channel.server.event.dto.OssCallbackParam;
import com.chagee.channel.server.event.dto.OssCallbackResult;
import com.chagee.channel.server.event.dto.OssPolicyResult;
import com.chagee.channel.server.event.model.OssCustomBO;
import com.chagee.channel.server.event.model.OssPolicyParam;
import com.chagee.channel.server.event.service.OssService;
import com.chagee.channel.server.util.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.rmi.ServerException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * oss上传管理Service实现类
 *
 * @author macro
 * @date 2018/5/17
 */
@Slf4j
@Service
public class OssServiceImpl implements OssService {

    @Value("${aliyun.oss.policy.expire}")
    private int ALIYUN_OSS_EXPIRE;
    @Value("${aliyun.oss.maxSize}")
    private Long ALIYUN_OSS_MAX_SIZE;
    @Value("${aliyun.oss.callback}")
    private String ALIYUN_OSS_CALLBACK;
    @Value("${aliyun.oss.bucketName}")
    private String ALIYUN_OSS_BUCKET_NAME;
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.dir.prefix}")
    private String ALIYUN_OSS_DIR_PREFIX;
    @Value("${aliyun.oss.privateBucketName}")
    private String ALIYUN_OSS_PRIVATE_BUCKET_NAME;
    @Value("${aliyun.oss.bucketType}")
    private Boolean ALIYUN_OSS_BUCKET_TYPE;
    @Value("${aliyun.oss.style}")
    private String style;
    @Value("${aliyun.oss.publicStyle}")
    private String publicStyle;
    private List<String> videoFormats;
    @Value("${aliyun.oss.accessKeyId:LTAI5tL5rDxaG1LkFASawiFz}")
    private String ALIYUN_OSS_ACCESS_KEY_ID;
    @Value("${aliyun.oss.accessKeySecret:BnJrNtNo5sT4JAHtKm5MuWP6QmqOZd}")
    private String ALIYUN_OSS_ACCESS_KEY_SECRET;

    @Value("${aliyun.mps.accessKeyId}")
    private String ACCESS_KEY_ID;
    @Value("${aliyun.mps.accessKeySecret}")
    private String SECRET_ACCESS_KEY;
    @Resource
    private OssConfig ossConfig;

    @Autowired
    public void VideoService(OssCustomConfig ossCustomConfig) {
        this.videoFormats = ossCustomConfig.getVideoFormats();
    }
    @Resource
    private OSSClient ossClient;
    @Resource
    private OssCustomConfig ossCustomConfig;

    /**
     * 签名生成
     *
     * @param param
     */
    @Override
    public OssPolicyResult policy(OssPolicyParam param) {
        String dir;
        boolean bucketType;
        if (ALIYUN_OSS_BUCKET_TYPE) {
            bucketType = StrUtil.isBlankIfStr(param.getBucketType()) || param.getBucketType();
        } else {
            bucketType = false;
        }
        BusinessEnum business = param.getBusiness();
       String bucketName;
        if (bucketType){
            bucketName=ALIYUN_OSS_PRIVATE_BUCKET_NAME;
        }else {
            bucketName=ALIYUN_OSS_BUCKET_NAME;
        }
        String storageDirectory = param.getStorageDirectory();
        // 存储目录
        if (business==null){
            if (StrUtil.isNotEmpty(storageDirectory)) {
                dir=storageDirectory;
            }else {
                dir = fetchDirOrDefault(param);
            }
        }else {
            dir = fetchDirOrDefault(param);
        }

        OssPolicyResult result = new OssPolicyResult();
        // 签名有效期
        DateTime expireEndTime = DateUtil.offsetSecond(new Date(), ALIYUN_OSS_EXPIRE);
        // 文件大小
        long maxSize = ALIYUN_OSS_MAX_SIZE * 1024L * 1024L;
        // 回调
        OssCallbackParam callback = new OssCallbackParam();
        callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);


        callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}&bucketName="+bucketName);
        callback.setCallbackSNI(true);

        callback.setCallbackBodyType("application/x-www-form-urlencoded");
        // 提交节点
        String action = "https://" + bucketName + "." + ALIYUN_OSS_ENDPOINT;
        try {
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expireEndTime, policyConds);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes(StandardCharsets.UTF_8));
            // 返回结果
            result.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
            result.setPolicy(policy);
            result.setSignature(signature);
            result.setDir(dir);
            result.setCallback(callbackData);
            result.setHost(action);
        } catch (Exception e) {
            log.error("签名生成失败", e);
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
        return result;
    }

    private String fetchDirOrDefault(OssPolicyParam param) {
        String dir = createDir();
        if (Objects.nonNull(param) && Objects.nonNull(param.getBusiness())) {
            Optional<OssCustomBO> ossCustomBO = ossCustomConfig.fetchCustomConfig(param.getBusiness());
            if (ossCustomBO.isPresent()) {
                dir = ossCustomBO.get().getPrefix();
            }
        }
        return dir;

    }

    @Override
    public OssCallbackResult callback(HttpServletRequest request) {
        OssCallbackResult result = new OssCallbackResult();
        String filename = request.getParameter("filename");
        String bucketName;
        String bucketNameUploaded = request.getParameter("bucketName");
        log.info("callback() called with parameters => 【filename = {}】=> 【bucketNameUploaded = {}】",filename,bucketNameUploaded);
        if (ALIYUN_OSS_BUCKET_TYPE) {
            if (StrUtil.equals(bucketNameUploaded,ALIYUN_OSS_PRIVATE_BUCKET_NAME)){
                bucketName = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
                // 签名有效期
                DateTime expireEndTime = DateUtil.offsetSecond(new Date(), ALIYUN_OSS_EXPIRE);
                try {
                    // 生成签名URL
                    URL signedUrl = ossClient.generatePresignedUrl(bucketName, filename, expireEndTime);
                    result.setFilename(String.valueOf(signedUrl));
                } catch (Exception e) {
                    log.error("生成的签名URL失败", e);
                } finally {
                    // 关闭OSSClient
                    ossClient.shutdown();
                }
            }else {
                filename = "https://".concat(bucketNameUploaded).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
                result.setFilename(filename);
            }
        } else {
            filename = "https://".concat(bucketNameUploaded).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
            result.setFilename(filename);
        }
        result.setSize(request.getParameter("size"));
        result.setMimeType(request.getParameter("mimeType"));
        result.setWidth(request.getParameter("width"));
        result.setHeight(request.getParameter("height"));
        return result;
    }

    @Override
    public SignedURLRep signedURL(SignedURLReq param) {
        SignedURLRep signedURLRep = new SignedURLRep();
        List<SignedURLRep.UrlVO> urlVOS = new ArrayList<>();
        // 签名有效期
        DateTime expireEndTime = DateUtil.offsetSecond(new Date(), ALIYUN_OSS_EXPIRE);
        List<String> urls = param.getUrls();
        if (CollUtil.isEmpty(urls)) {
            log.error("urls为空");
            return signedURLRep;
        }
        try {
            for (String url : urls) {
                SignedURLRep.UrlVO urlVO = new SignedURLRep.UrlVO();
                String p = "^(https?://[^/]+)";
                String urlPath = ReUtil.get(p, url, 1);
                String httpsUrl = "https://" + ALIYUN_OSS_PRIVATE_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
                String httpUrl = "http://" + ALIYUN_OSS_PRIVATE_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
                if (StrUtil.equals(httpsUrl,urlPath)||StrUtil.equals(httpUrl,urlPath)) {
                    // 匹配以 http:// 或 https:// 开头的任意字符直到第一个斜杠后的所有字符，不包括查询参数
                    String pattern = "(?:https?://)?[^/]+(/[^?]+)";
                    String path = ReUtil.get(pattern, url, 1);
                    if (path == null) {
                        log.error("URL 格式不正确");
                    } else {
                        // 去掉开头的斜杠
                        path = path.startsWith("/") ? path.substring(1) : path;
                        // 生成签名URL
                        URL signedUrl = ossClient.generatePresignedUrl(ALIYUN_OSS_PRIVATE_BUCKET_NAME, URLUtil.decode(path), expireEndTime);
                        log.info("生成的签名URL：{}", signedUrl);
                        urlVO.setUrl(url);
                        urlVO.setSignedUrl(String.valueOf(signedUrl));
                    }
                }else {
                    urlVO.setUrl(url);
                    urlVO.setSignedUrl(url);
                }
                urlVOS.add(urlVO);
            }
        } catch (Exception e) {
            log.error("生成的签名URL失败", e);
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
        signedURLRep.setUrls(urlVOS);
        return signedURLRep;
    }

    @Override
    public String createDir() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return ALIYUN_OSS_DIR_PREFIX + sdf.format(new Date());
    }
    @Override
    public SignedURLRep firstFrameOfVideo(SignedURLReq param){
        SignedURLRep signedURLRep = new SignedURLRep();
        List<SignedURLRep.UrlVO> urlVOS = new ArrayList<>();
        // 签名有效期
        DateTime expireEndTime = DateUtil.offsetSecond(new Date(), ALIYUN_OSS_EXPIRE);
        List<String> urls = param.getUrls();
        if (CollUtil.isEmpty(urls)) {
            log.error("urls为空");
            return signedURLRep;
        }
        try {
            for (String url : urls) {
                SignedURLRep.UrlVO urlVO = new SignedURLRep.UrlVO();
                String p = "^(https?://[^/]+)";
                String urlPath = ReUtil.get(p, url, 1);
                String httpsUrl = "https://" + ALIYUN_OSS_PRIVATE_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
                String httpUrl = "http://" + ALIYUN_OSS_PRIVATE_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
                // 匹配以 http:// 或 https:// 开头的任意字符直到第一个斜杠后的所有字符，不包括查询参数
                String pattern = "(?:https?://)?[^/]+(/[^?]+)";
                String path = ReUtil.get(pattern, url, 1);
                if (StrUtil.equals(httpsUrl,urlPath)||StrUtil.equals(httpUrl,urlPath)) {
                    if (path == null) {
                        log.error("URL 格式不正确");
                    } else {
                        // 去掉开头的斜杠
                        path = path.startsWith("/") ? path.substring(1) : path;
                        URL signedUrl;
                        if (isVideoFormat(path, videoFormats)) {
                            // 生成签名URL
                            GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(ALIYUN_OSS_PRIVATE_BUCKET_NAME, URLUtil.decode(path), HttpMethod.GET);
                            req.setExpiration(expireEndTime);
                            req.setProcess(style);
                            signedUrl = ossClient.generatePresignedUrl(req);
                            log.info("signedUrl={}",JSONUtil.parse(signedUrl));
                        }else {
                            signedUrl = ossClient.generatePresignedUrl(ALIYUN_OSS_PRIVATE_BUCKET_NAME, URLUtil.decode(path), expireEndTime);
                        }
                        log.info("生成的签名URL：{}", signedUrl);
                        urlVO.setUrl(url);
                        urlVO.setSignedUrl(String.valueOf(signedUrl));
                    }
                }else {
                    String signedUrl = url;
                    if (isVideoFormat(path, videoFormats)) {
                        signedUrl =signedUrl+publicStyle;
                    }
                    urlVO.setUrl(url);
                    urlVO.setSignedUrl(signedUrl);
                }
                urlVOS.add(urlVO);
            }
        } catch (Exception e) {
            log.error("生成的签名URL失败", e);
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
        signedURLRep.setUrls(urlVOS);
        return signedURLRep;
    }

    @Override
    public void deleteFile(OssPolicyParam param) {
        OSS ossClient = new OSSClient(ALIYUN_OSS_ENDPOINT, ALIYUN_OSS_ACCESS_KEY_ID, ALIYUN_OSS_ACCESS_KEY_SECRET);
        try {
            ossClient.deleteObject(ALIYUN_OSS_BUCKET_NAME, param.getStorageDirectory());
        } catch (OSSException oe) {
            log.info("Caught an OSSException, which means your request made it to OSS, " +
                    "but was rejected with an error response for some reason." +
                    "Error Message:{},Error Code:{},Request ID:{},Host ID:{}",oe.getErrorMessage(),oe.getErrorCode(),oe.getRequestId(),oe.getHostId());
        } catch (Throwable ce) {
            log.info("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.Error Message:{}",ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    @Override
    public String uploadByUrl(UploadOssRequest req) {
        byte[] bytes = HttpUtils.downloadBytes(req.getUrl());
        return upload(bytes, req.getFileName());
    }

    @Override
    public String upload(String bucketName, byte[] pic, String fileName) {
        if(StrUtil.isEmpty(bucketName)){
            bucketName = ALIYUN_OSS_BUCKET_NAME;
        }

        // 创建PutObjectRequest对象
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, new ByteArrayInputStream(pic));
        // 上传文件
        OSSClient ossClient = new OSSClient(ALIYUN_OSS_ENDPOINT, ossConfig.getALIYUN_OSS_ACCESSKEYID(), ossConfig.getALIYUN_OSS_ACCESSKEYSECRET());
        try {
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            if (StringUtils.isBlank(putObjectResult.getRequestId())) {
                throw new BizException(BizErrorCode.FAIL);
            }
        } catch (Exception e) {
            log.error("上传文件失败", e);
        } finally {
            ossClient.shutdown();
        }
        return "https://".concat(bucketName).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(fileName);
    }

    @Override
    public String upload(byte[] pic, String fileName) {
        return upload(null, pic, fileName);
    }

    private boolean isVideoFormat(String fileExtension, List<String> videoFormats) {
        if (videoFormats == null) {
            return false;
        }
        for (String format : videoFormats) {
            if (fileExtension.endsWith(format)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int toMP4(FileNameListReq fileNamelist)  {
        int count=0;
        NewFile newFile=new NewFile();
        // 配置阿里云客户端
        String accessKeyId=null;
        String accessKeySecret=null;
        try{
//             accessKeyId =com.aliyun.darabonba.env.EnvClient.getEnv("ACCESS_KEY_ID");
//            accessKeySecret=com.aliyun.darabonba.env.EnvClient.getEnv("SECRET_ACCESS_KEY");
            accessKeyId =ACCESS_KEY_ID;
            accessKeySecret=SECRET_ACCESS_KEY;
        }
        catch (Exception e) {
            e.printStackTrace();
        } ;
//        String accessKeyId = ossClient.getCredentialsProvider().getCredentials().getAccessKeyId();
        log.info("accessKeyId:{}",accessKeyId);
//        String accessKeySecret = ossClient.getCredentialsProvider().getCredentials().getSecretAccessKey();
        log.info("accessKeySecret:{}",accessKeySecret);
        String regionId = "cn-shanghai"; // MPS服务所在区域
        Config config = new Config();
        config.setAccessKeyId(accessKeyId);
        config.setAccessKeySecret(accessKeySecret);
        config.setRegionId(regionId);
        log.info("config{}",config);
        Client client=null;
        try {
            client = new com.aliyun.mts20140618.Client(config);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("client{}",client);
        RuntimeOptions runtime = new RuntimeOptions();
        for (NewFile file : fileNamelist.getFiles()) {
            // Find the index of ".com"
            log.info("fileName:{}", file.getFileName());
            if (!file.getFileName().equals(this.getMP4(file.getFileName()))) {
                log.info("this.getMP4(file.getFileName():{}", this.getMP4(file.getFileName()));
                continue;
            }
            int index = file.getFileName().indexOf(".com/");
            String path = new String();
            String url = new String();
            if (index != -1) {
                path = file.getFileName().substring(index + 5);
                url = file.getFileName().substring(0, index + 5);
            }
            log.info("path+url{}", path + url);
            // 输入和输出的OSS信息
            String inputBucket = new String();
            String outputBucket = new String();
            if (ALIYUN_OSS_BUCKET_TYPE) {
                inputBucket = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
                outputBucket = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
            } else {
                inputBucket = ALIYUN_OSS_BUCKET_NAME;
                outputBucket = ALIYUN_OSS_BUCKET_NAME;
            }
            String inputObject = path;
            String outputObject = path.split("\\.")[0] + ".mp4";
            // 媒体处理模板ID（需要预先设置好）
            String templateId = "S00000001-200000"; // 预定义的转码模板ID，可以在MPS控制台设置
            // 创建提交转码作业的请求
            SubmitJobsRequest request = new SubmitJobsRequest();
            request.setPipelineId("16578710314a42c9ac6679cbda4dc04b");
            request.setInput("{\"Bucket\":\"" + inputBucket + "\",\"Location\":\"oss-cn-shanghai\",\"Object\":\"" + inputObject + "\"}");
            request.setOutputBucket(outputBucket);
            request.setOutputLocation("oss-cn-shanghai");
            request.setOutputs("[{\"OutputObject\":\"" + outputObject + "\",\"TemplateId\":\"" + templateId + "\"}]");
            log.info("SubmitJobsRequest:{}", JSONUtil.toJsonStr(request));
            try {
                // 提交转码作业
                log.info("开始执行转码");
                SubmitJobsResponse response = client.submitJobsWithOptions(request, runtime);
                log.info("SubmitJobsResponse:{}", response);
//            SubmitJobsResponse response = client.getAcsResponse(request);
                log.info("JobId: " + response.getBody().getJobResultList().getJobResult().get(0).getJob().getJobId());
                newFile.setJobId(response.getBody().getJobResultList().getJobResult().get(0).getJob().getJobId());
            } catch (ServerException e) {
                log.warn("发起转换失败:", e);
            } catch (Exception e) {
                log.warn("发起转换失败原因:", e);
            }
            newFile.setFileName(file.getFileName());
            newFile.setNewFileName(url + outputObject);
            if(newFile.getJobId()!=null){
                count++;
            }

        }
        return count;
    }
    @Override
    public String getMP4(String objectName) {
        try {
            // 配置阿里云 OSS 访问凭证
            String accessKeyId = ossClient.getCredentialsProvider().getCredentials().getAccessKeyId();
            String accessKeySecret = ossClient.getCredentialsProvider().getCredentials().getSecretAccessKey();
            String endpoint =ALIYUN_OSS_ENDPOINT; // OSS Endpoint
            // 初始化 OSS 客户端
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            log.info("入参objectName:{}",objectName);
            int index = objectName.indexOf(".com/");
            String path=new String();
            String url=new String();
            if (index != -1) {
                path =objectName.substring(index + 5);
                url = objectName.substring(0, index + 5);
            }
//            String bucketName=ALIYUN_OSS_PRIVATE_BUCKET_NAME;
            String bucketName=new String();
            if (ALIYUN_OSS_BUCKET_TYPE) {
                bucketName = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
            } else {
                bucketName = ALIYUN_OSS_BUCKET_NAME;
            }
            log.info("mp4:{}",bucketName);
            String mp4ObjectName = path.split("\\.")[0] + ".mp4";
            log.info("mp4:{}",mp4ObjectName);
            // 检查对象是否存在
            boolean exists = ossClient.doesObjectExist(bucketName, mp4ObjectName);
            if (exists) {
                log.info("Object " + objectName + "exists_in_bucket " + bucketName + ".");
                log.info("newurl:{}",url+mp4ObjectName);
                return url+mp4ObjectName;
            } else {
                log.info("Object " + objectName + "does_not_exist_in_bucket " + bucketName + ".");
            }
        } catch (Exception e) {
            log.warn("Error: " + e.getMessage());
        }finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
        return objectName;
    }

    @Override
    public boolean doesObjectExist(String ossUrl) {
        try {
            // 配置阿里云 OSS 访问凭证
            String accessKeyId = ossClient.getCredentialsProvider().getCredentials().getAccessKeyId();
            String accessKeySecret = ossClient.getCredentialsProvider().getCredentials().getSecretAccessKey();
            String endpoint =ALIYUN_OSS_ENDPOINT; // OSS Endpoint
            // 初始化 OSS 客户端
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

            int index = ossUrl.indexOf(".com/");
            String objectName=new String();
            if (index != -1) {
                objectName = ossUrl.substring(index + 5);
            }
            String bucketName;
            if (ALIYUN_OSS_BUCKET_TYPE) {
                bucketName = ALIYUN_OSS_PRIVATE_BUCKET_NAME;
            } else {
                bucketName = ALIYUN_OSS_BUCKET_NAME;
            }

            // 检查对象是否存在
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            log.info("Object: {}, exists: {} ", objectName, exists);
            return exists;
        } catch (Exception e) {
            log.warn("Error: " + e.getMessage());
            return false;
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }

    public static String extractPathFromURL(String url) {
		try {
			java.net.URL urlObj = new java.net.URL(url);
			// remove the leading "/"
			return urlObj.getPath().substring(1);
		} catch (java.net.MalformedURLException e) {
			log.error("extractPathFromURL() called with exception => 【url = {}】",url,e);
			return null;
		}
	}
	public static String changeExtensionToPdf(String path,String target) {
		if (path != null && path.contains(".")) {
			int dotIndex = path.lastIndexOf('.');
			return path.substring(0, dotIndex) + "." + target;
		}
		return null;
	}
	public static String extractFileExtension(String url) {
		try {
			java.net.URL urlObj = new java.net.URL(url);
			String path = urlObj.getPath();
			int dotIndex = path.lastIndexOf('.');
			if (dotIndex != -1 && dotIndex < path.length() - 1) {
				return path.substring(dotIndex + 1);
			} else {
				// No extension found
				return "";
			}
		} catch (java.net.MalformedURLException e) {
			log.error("extractFileExtension() called with exception => 【url = {}】",url,e);
			return null;
		}
	}

	@Override
	public DocumentConversionRep documentConversion(DocumentConversionReq req) {
		log.info("documentConversion() called with parameters => 【req = {}】",req);
		DocumentConversionRep documentConversionRep = new DocumentConversionRep();
		// 配置阿里云 OSS 访问凭证
		String accessKeyId = ossClient.getCredentialsProvider().getCredentials().getAccessKeyId();
		String accessKeySecret = ossClient.getCredentialsProvider().getCredentials().getSecretAccessKey();
		String endpoint =ALIYUN_OSS_ENDPOINT;
		// 初始化 OSS 客户端
		OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

		DocumentConversionTargetEnum target = req.getTarget();
		String source = extractFileExtension(req.getKey());

		String key = req.getKey();
		key = extractPathFromURL(key);
		String saveAsKey = changeExtensionToPdf(key,target.getDesc());

		if (StrUtil.equals(DocumentConversionTargetEnum.TXT.getDesc(), target.getDesc())) {
            assert source != null;
            if (!(DocumentConversionSourceEnum.isWordDocument(source) || DocumentConversionSourceEnum.isPowerPointDocument(source))) {
                log.error("documentConversion() called with exception =>code={}，message:{} ", BizErrorCode.TXT_FAIL.getErrorCode(), BizErrorCode.TXT_FAIL.getErrorMsg());
                throw new BizException(BizErrorCode.TXT_FAIL);
            }
        }

		try {
			StringBuilder styleBuilder = new StringBuilder();
			styleBuilder.append("doc/convert,target_"+target.getDesc()+",source_"+source);
			styleBuilder.append("|sys/saveas,");
			styleBuilder.append("o_" + Base64.getUrlEncoder().withoutPadding().encodeToString(saveAsKey.getBytes()));
			styleBuilder.append(",");
			styleBuilder.append("b_" + Base64.getUrlEncoder().withoutPadding().encodeToString(ALIYUN_OSS_BUCKET_NAME.getBytes()));
			AsyncProcessObjectRequest request = new AsyncProcessObjectRequest(ALIYUN_OSS_BUCKET_NAME, key, styleBuilder.toString());
			log.info("ossClient.asyncProcessObject() => request={}",JSONUtil.toJsonStr(request));
			AsyncProcessObjectResult asyncProcessObject = ossClient.asyncProcessObject(request);
			log.info("ossClient.asyncProcessObject() => asyncProcessObject={}", JSONUtil.toJsonStr(asyncProcessObject));


			String url = changeExtensionToPdf(req.getKey(), target.getDesc());
			SignedURLReq signedURLReq = new SignedURLReq();
			signedURLReq.setUrls(Collections.singletonList(url));
			SignedURLRep signedURLRep = this.signedURL(signedURLReq);
			if (signedURLRep!=null&&CollUtil.isNotEmpty(signedURLRep.getUrls())){
				List<SignedURLRep.UrlVO> urls = signedURLRep.getUrls();
				url = urls.get(0).getSignedUrl();
			}
			documentConversionRep.setUrl(url);
			return documentConversionRep;
		} catch (OSSException oe) {
			log.error("Caught an OSSException, which means your request made it to OSS, "
				+ "but was rejected with an error response for some reason.");
			log.error("Error Message: " + oe.getMessage());
			log.error("Error Code:       " + oe.getErrorCode());
			log.error("Request ID:      " + oe.getRequestId());
			log.error("Host ID:           " + oe.getHostId());
			throw new BizException(BizErrorCode.DOCUMENT_CONVERSION_FAIL);
		} catch (ClientException ce) {
			log.error("Caught an ClientException, which means the client encountered "
				+ "a serious internal problem while trying to communicate with OSS, "
				+ "such as not being able to access the network.");
			log.error("Error Message: " + ce.getMessage());
			throw new BizException(BizErrorCode.DOCUMENT_CONVERSION_FAIL);
		} finally {
			/*
			 * Do not forget to shut down the client finally to release all allocated resources.
			 */
			ossClient.shutdown();
		}
	}
}
